﻿using Analyse.DrawingPerformance.Model;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Text;
using System.IO;

namespace Analyse.DrawingPerformance.Contract
{
    public class DefaultDotNetDrawingEngine : IDrawingEngine
    {
        public byte[] Draw(int width, int height, List<BaseDrawElement> drawElements)
        {
            var functions = new Dictionary<Type, Func<Graphics, BaseDrawElement, bool>>();
            functions.Add(typeof(ImageDrawElement), DrawImage);
            functions.Add(typeof(TextDrawElement), DrawText);

            using (var image = new Bitmap(width, height))
            using (var canvas = Graphics.FromImage(image))
            {
                canvas.Clear(Color.White);

                if (drawElements != null)
                {
                    foreach (var drawElement in drawElements)
                    {
                        functions.TryGetValue(drawElement.GetType(), out var function);
                        function?.Invoke(canvas, drawElement);
                    }
                }

                var imageData = GetBytes(image);
                return imageData;
            }
        }

        private static byte[] GetBytes(Image image)
        {
            byte[] data;
            using (var memoryStream = new MemoryStream())
            {
                image.Save(memoryStream, ImageFormat.Png);
                data = memoryStream.ToArray();
            }

            return data;
        }

        private bool DrawImage(Graphics canvas, BaseDrawElement drawElement)
        {
            var item = drawElement as ImageDrawElement;

            using (var image = Image.FromFile(item.ImagePath))
            {
                canvas.DrawImage(image, item.X, item.Y);
            }

            return true;
        }

        private bool DrawText(Graphics canvas, BaseDrawElement drawElement)
        {
            var item = drawElement as TextDrawElement;
            var color = ColorTranslator.FromHtml(item.Color);

            Font font = null;
            try
            {
                if (string.IsNullOrEmpty(item.FontPath))
                {
                    font = new Font("Arial", item.Size);
                }
                else
                {
                    using (var collection = new PrivateFontCollection())
                    {
                        collection.AddFontFile(item.FontPath);
                        font = new Font(collection.Families[0], item.Size);
                    }
                }

                using (var solidBrush = new SolidBrush(color))
                {
                    canvas.DrawString(item.Text, font, solidBrush, item.X, item.Y);
                }
            }
            finally
            {
                font.Dispose();
            }

            return true;
        }
    }
}
